//Copyright (C) 2009 Ron Coleman. Contact: ronncoleman@gmail.com
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 3 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this library; if not, write to the Free Software
//Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

package org.workplicity.android.cia.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;

import org.workplicity.android.cia.R;
import org.workplicity.android.cia.application.ELogApplication;
import org.workplicity.android.cia.ui.ElogEditActivity;
import org.workplicity.android.cia.ui.mainfragments.TitlesFragment;
import org.workplicity.android.cia.util.AndroidHelper;
import org.workplicity.android.cia.util.CIAHelper;
import org.workplicity.android.cia.util.Pair;
import org.workplicity.elog.entry.Elog;
import org.workplicity.elog.entry.ElogUser;
import org.workplicity.util.Helper;

import com.mongodb.BasicDBObject;
import com.mongodb.util.JSON;

import android.animation.Animator;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentTransaction;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 
 * @author Brian Gormanly
 * @version 1.0
 * 
 * <p>Main Activity after login.  Where work order navigation takes place
 * and ties in to all other screens.  Consists of two fragments, one
 * for the spinner listing the work orders and one for the description
 * and work done on the selected work order.</p>
 */

public class MainActivity extends Activity implements ActionBar.OnNavigationListener {

	private static final int NOTIFICATION_DEFAULT = 1;
    private static final String ACTION_DIALOG = "org.workplicity.android.cia.ui.action.DIALOG";
    
    /**
     * Application object, used to reference the application layer
     */
    ELogApplication app;

    private View mActionBarView;
    private Animator mCurrentTitlesAnimator;
    private int mLabelIndex = 1;
    private int mThemeId = -1;

    /**
     * Contains the list of users in the database
     */
    public String[] userNames = null;

    private long end;

    private long start;
    
    // keep track of running threads
    private boolean thread1;
    private boolean thread2;

    /**
     * Activity constructor - initializes the activity
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        app = (ELogApplication)getApplication();

        if(savedInstanceState != null && savedInstanceState.getInt("theme", -1) != -1) {
            mThemeId = savedInstanceState.getInt("theme");
            this.setTheme(mThemeId);
        }
        else {
        	// default
        	this.setTheme(R.style.AppTheme_Light);
        }

        setContentView(R.layout.main);

        ActionBar bar = getActionBar();
        
        // get the resourcess available
        Resources res = getResources();
        mActionBarView = getLayoutInflater().inflate(R.layout.action_bar_custom, null);

        bar.setCustomView(mActionBarView);
        bar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_USE_LOGO);
        bar.setDisplayShowHomeEnabled(true);
        
        
        refresh();
        updateAllWorkOrders();

     
    }

    @Override
	protected void onRestart() {
		// TODO Auto-generated method stub
		super.onRestart();
		// update the fragment with the list
        TitlesFragment myFrag = (TitlesFragment)getFragmentManager().findFragmentById(R.id.frag_title);
        myFrag.populateTitles();
        
        updateAllWorkOrders();
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		// update the fragment with the list
        TitlesFragment myFrag = (TitlesFragment)getFragmentManager().findFragmentById(R.id.frag_title);
        myFrag.populateTitles();
        
        updateAllWorkOrders();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
	}

	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		super.onBackPressed();
		LogoutUser logoutThread = new LogoutUser();
		logoutThread.execute();
		
	}

	/**
     * <p>Keeps the activity and the fragments of the activity up to date with the Application layer data view</p>
     * 
     * <p>Calling this method will cause all the controls on this activity and all child fragments to update. The
     * data model that is used for the update is in the Android Application layer.  Colling this method does
     * not actually update the application layer data to that on the server, if that is necessary it must be
     * done separately first.</p>
     */
    public void refresh() {
    	// User list spinner
        Spinner userSpinner = (Spinner) findViewById(R.id.userSpinner);
        ArrayAdapter<String> userAdapter;
        try {
        	userAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, app.getAllUsersUsernames());
        }
        catch(Exception e) {
        	String[] tempUser = new String[1];
			tempUser[0] = getString(R.string.Loading);
			userAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, tempUser);
        }
        
        userAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);    
        userSpinner.setAdapter(userAdapter);
        
        // user spinner select event
        userSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
                updateAllWorkOrders();
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });

        // get the types available
        String[] types = new String[4];
        types[0] = Elog.Type.ANY.toString();
        types[1] = Elog.Type.NORMAL.toString();
        types[2] = Elog.Type.UNUSUAL.toString();
        types[3] = Elog.Type.SUMMARY.toString();
        
        // Type spinner
        final Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner);
        ArrayAdapter<String> typeAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, types);
        typeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        typeSpinner.setAdapter(typeAdapter);
        
        // type spinner select event
        typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
                updateAllWorkOrders();
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });
        
        // get the statuses available
        String[] statuses = new String[3];
        statuses[0] = Elog.Status.ANY.toString();
        statuses[1] = Elog.Status.NOTDONE.toString();
        statuses[2] = Elog.Status.DONE.toString();
        
        // Status spinner
        Spinner statusSpinner = (Spinner) findViewById(R.id.statusSpinner);
        ArrayAdapter<String> statusAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, statuses);
        statusAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        statusSpinner.setAdapter(statusAdapter);
        
        // status spinner select event
        statusSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
            	updateAllWorkOrders();
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });
        
        // Age spinner
        Spinner ageSpinner = (Spinner) findViewById(R.id.ageSpinner);
        ArrayAdapter<String> ageAdapter;
        try {
        	ageAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, CIAHelper.AGES);
        }
        catch(Exception e) {
        	String[] tempUser = new String[1];
			tempUser[0] = getString(R.string.Loading);
			ageAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, tempUser);
        }
        
        ageAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        ageSpinner.setAdapter(ageAdapter);

        // age spinner select event
        ageSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
            	updateAllWorkOrders();
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });
    }
    
    /**
     * Creates the GetWorkOrders AsyncTask to retrieve work orders from the database
     * 
     * @see GetWorkOrders Class documentation for more information.
     */
    protected void updateAllWorkOrders() {
		// get the user selected
    	Spinner userSpinner = (Spinner) findViewById(R.id.userSpinner);
    	String selectedUsername = userSpinner.getSelectedItem().toString();
    	ElogUser selectedUser = app.getUserByUserName(selectedUsername);
    	
    	// get the type selected
        Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner);
        
        // get the type chosen
        String chosenType = typeSpinner.getSelectedItem().toString();

        // initialize a Elog.Type
        Elog.Type selectedType;
        
        // Decision on the elog type
        if(chosenType == Elog.Type.NORMAL.toString()) {
        	selectedType = Elog.Type.NORMAL;
        }
        else if(chosenType == Elog.Type.UNUSUAL.toString()) {
        	selectedType = Elog.Type.UNUSUAL;
        }
        else if(chosenType == Elog.Type.SUMMARY.toString()) {
        	selectedType = Elog.Type.SUMMARY;
        }
        else {
        	// set to any
        	selectedType = Elog.Type.ANY;
        }
    	
    	// get the status selected
        Spinner statusSpinner = (Spinner) findViewById(R.id.statusSpinner);
        
        // get the status chosen
        String chosenStatus = statusSpinner.getSelectedItem().toString();
        
        // initialize a Elog.Status
        Elog.Status selectedStatus;
        
        // decisison on the elog status
        if(chosenStatus == Elog.Status.DONE.toString()) {
        	selectedStatus = Elog.Status.DONE;
        }
        else if(chosenStatus == Elog.Status.NOTDONE.toString()) {
        	selectedStatus = Elog.Status.NOTDONE;
        }
        else {
        	// set to any
        	selectedStatus = Elog.Status.ANY;
        }
    	
    	// get the age seleceted
        Spinner ageSpinner  = (Spinner) findViewById(R.id.ageSpinner);
        
        // get the age chosen
        int selectedAge = ageSpinner.getSelectedItemPosition();

        // check to see if there is an available thread
        if(!this.isThread1()) {
        	// set the thread to active
        	this.setThread1(true);
        	
        	// instantiate and call the async thread to retrieve the info.
        	GetWorkOrders asyncQ = new GetWorkOrders(selectedUser, selectedType, selectedStatus, selectedAge, 1);
    		asyncQ.execute();
        }
        /*
        else if (!this.isThread2()) {
        	// set the thread to active
        	this.setThread2(true);
        	
        	// instantiate and call the async thread to retrieve the info.
        	GetWorkOrders asyncQ = new GetWorkOrders(selectedUser, selectedType, selectedStatus, selectedAge, 2);
    		asyncQ.execute();
        }
        else {
        	// no threads available
        	
        }
        */
	 }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        
        case R.id.editElog:
        	Intent myIntent = new Intent(MainActivity.this, ElogEditActivity.class);
        	
        	// check to see if there is a selected list item
        	TitlesFragment myFrag = (TitlesFragment)getFragmentManager().findFragmentById(R.id.frag_title);
	        try {
	        	this.getApp().setCurrentElog(this.getApp().getAllElogs().get(myFrag.mCurPosition));
	        	
	        	// check to see if the user selected a work order to edit
	        	if(app.getCurrentElog().getId() != 0) {
	        		// set create mode to false
	            	app.setCreateMode(false);
	            	
	                startActivityForResult(myIntent, 0);
	            	return true;
	        	}
	        }
	        catch(Exception e) {
	        	// user has not selected a valid work order
        		Toast toast=Toast.makeText(this, R.string.ChooseWO, 2000);
        		toast.show();
        		return true;
	        }

        	
        
        case R.id.composeElog:
        	Intent myIntent2 = new Intent(MainActivity.this, ElogEditActivity.class);
        	app.setCurrentElog(new Elog());
        	app.getCurrentElog().setId(-1);
        	
        	// set create mode to true
        	app.setCreateMode(true);
        	
            startActivityForResult(myIntent2, 0);
        	return true;

        case R.id.toggleTheme:
            if (mThemeId == R.style.AppTheme_Dark) {
                mThemeId = R.style.AppTheme_Light;
            } else {
                mThemeId = R.style.AppTheme_Dark;
            }
            this.recreate();
            return true;

        case R.id.showHelpDialog:
            showDialog("CIAElog is a branch of Workplicity.\nThis is an example help dialog box that will contain information on how to use the screen you are looking at.");
            return true;
            
        case R.id.showAboutDialog:
            showDialog("CIAElog is a branch of Workplicity.\nAndroid Client for CIAElog Version 1.0\n\nContributors:\nBrian Gormanly");
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        if (ACTION_DIALOG.equals(intent.getAction())) {
            showDialog(intent.getStringExtra(Intent.EXTRA_TEXT));
        }
    }

    void showDialog(String text) {
        // DialogFragment.show() will take care of adding the fragment
        // in a transaction.  We also want to remove any currently showing
        // dialog, so make our own transaction and take care of that here.
        FragmentTransaction ft = getFragmentManager().beginTransaction();

        DialogFragment newFragment = MyDialogFragment.newInstance(text);

        // Show the dialog.
        newFragment.show(ft, "dialog");
    }

    void showNotification(boolean custom) {
        
    }

    PendingIntent getDialogPendingIntent(String dialogText) {
        return PendingIntent.getActivity(
                this,
                dialogText.hashCode(), // Otherwise previous PendingIntents with the same
                                       // requestCode may be overwritten.
                new Intent(ACTION_DIALOG).putExtra(Intent.EXTRA_TEXT, dialogText).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0);
    }



    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        
        return true;
    }

    @Override
    public void onSaveInstanceState (Bundle outState) {
        super.onSaveInstanceState(outState);
        //ActionBar bar = getActionBar();
        //int category = bar.getSelectedTab().getPosition();
        //outState.putInt("category", category);
        //outState.putInt("theme", mThemeId);
    }
    
    
    public ELogApplication getApp() {
		return app;
	}


	public void setApp(ELogApplication app) {
		this.app = app;
	}


    public static class MyDialogFragment extends DialogFragment {

        public static MyDialogFragment newInstance(String title) {
            MyDialogFragment frag = new MyDialogFragment();
            Bundle args = new Bundle();
            args.putString("text", title);
            frag.setArguments(args);
            return frag;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            String text = getArguments().getString("text");

            return new AlertDialog.Builder(getActivity()).setTitle("CIAElog Ver. 1")
            	.setMessage(text)
                .setPositiveButton(android.R.string.ok,
            		new DialogInterface.OnClickListener() {
                        @Override
						public void onClick(DialogInterface dialog, int whichButton) {
                        }
                    }).create();
        }
    }


	@Override
	public boolean onNavigationItemSelected(int itemPosition, long itemId) {
		// Do Something
		
		String a = "testing";
	    
		return false;
	}
	
	
	// gettors and settors
	public boolean isThread1() {
		return thread1;
	}

	public void setThread1(boolean thread1) {
		this.thread1 = thread1;
	}

	public boolean isThread2() {
		return thread2;
	}

	public void setThread2(boolean thread2) {
		this.thread2 = thread2;
	}
	
	/**
	  * @author Brian Gormanly
	  * @version 1.0
	  * 
	  * <p>AsyncTask that logs out the user</p>
	  * 
	  */
	class LogoutUser extends AsyncTask<Void, Void, Void> {
		@Override
		protected Void doInBackground(Void... params) {
			try {
				Looper.myLooper();
				Looper.prepare();
			}
			catch(Exception e) {
				// Looper only needs to be created if the thread is new, if reusing the thread we end up here
			}
			
			try {
				Helper.logout(app.getLoggedInUser(), app.getContext());
			}
			catch(Exception e) {
				
			}
			return null;
		}
		protected void onPostExecute(ArrayList<Elog> elogs) {
			
		}
	}
	
	
	/**
	 * @author Brian Gormanly
	 * @version 1.0
	 * 
	 * <p>AsyncTask that retrieves all Workorders from the database that fit the criteria chosen by
	 * the user.</p>
	 * 
	 * <p>Using the criteria that the user chooses will retrieve all workorders from the database and
	 * populates the application layer's data with the returned logs.</p>
	 */
	class GetWorkOrders extends AsyncTask<Object, Integer, ArrayList<Elog>> {

		private ElogUser selectedUser;
		private Elog.Type selectedType;
		private Elog.Status selectedStatus;
		private int selectedAge;
		private int thread;
		
		// override the constructor to pass parameters needed
		public GetWorkOrders(ElogUser user, Elog.Type type, Elog.Status status, int age, int thread) {
			this.setSelectedUser(user);
			this.setSelectedType(type);
			this.setSelectedStatus(status);
			this.setSelectedAge(age);
			this.setThread(thread);
		}
		
		@Override
		protected ArrayList<Elog> doInBackground(Object... arg0) {
			try {
				Looper.myLooper();
				Looper.prepare();
			}
			catch(Exception e) {
				// Looper only needs to be created if the thread is new, if reusing the thread we end up here
			}
			
			try {

				// Get the subordinates, including the user as a subordinate of him/herself
		        HashSet<ElogUser> subs = new HashSet<ElogUser>();

		        subs.add(this.getSelectedUser());

		        app.gatherSubordinates(app.getLoggedInUser(), subs);

		        // Set the subordinate repositories as the collections
		        String collections = "";

		        for(ElogUser sub : subs) {
		            if(collections.length() != 0)
		                collections += "|";
		            collections += sub.getReposTitle();
		        }
		        
		        // get the start and end age from the age combobox itemseleted
		        String key = CIAHelper.AGES[this.getSelectedAge()];

		        HashMap<String, Pair<Long, Long>> map = CIAHelper.getAgeMap();

		        Long starts = map.get(key).getStarts();
		        Long ends = map.get(key).getEnds();

		        // Set the data parallel criteria
		        BasicDBObject range = new BasicDBObject();
		        range.put("$gt", starts);
		        range.put("$lte", ends);
		        
		        BasicDBObject predicate = new BasicDBObject();

		        predicate.put("entry.updateDate", range);

		        if(this.getSelectedStatus() != Elog.Status.ANY)
		            predicate.put("entry.status", this.getSelectedStatus() + "");

		        if(this.getSelectedType() != Elog.Type.ANY)
		            predicate.put("entry.type", this.getSelectedType() + "");


		        String criteria = JSON.serialize(predicate);
		        ArrayList<Elog> elogs = Helper.query(collections,criteria, app.getContext());

		        Collections.sort(elogs, new Comparator() {
		            public int compare(Object o1, Object o2) {
		                Date d1 = ((Elog) o1).getUpdateDate();
		                Date d2 = ((Elog) o2).getUpdateDate();
		                return d2.compareTo(d1);
		            }
		        });
		        
		        return elogs;
		       
	        }
	        catch(Exception e) {
	        	e.printStackTrace();
	        	return null;
	        }
		}
		
		protected void onPostExecute(ArrayList<Elog> elogs) {
			try {
		        for(Elog elog : elogs) {
		        	android.util.Log.d("alarm", "!!!!!!!!!!!Elog: " + elog.getDescription());
		        }
		        
		        app.setAllElogs(elogs);
		        
		        // update the fragment with the list
		        TitlesFragment myFrag = (TitlesFragment)getFragmentManager().findFragmentById(R.id.frag_title);
		        myFrag.populateTitles();
		        
		        android.util.Log.d("alarm", "^^^^^^^^^^^^^^^^^!All done elogs!!!!^^^^^^^^^^^^^^^^^^^^^^^^");
		        
		        
			}
			catch(Exception e) {
				// do nothing, something went wrong with the data transfer
			}
			finally {
				// unset the thread
		        if(this.getThread()== 1) {
		        	setThread1(false);
		        }
		        else if(this.getThread() == 2) {
		        	setThread2(false);
		        }
			}
	        
	    }
		
		// gettors and settors
		
		public ElogUser getSelectedUser() {
			return selectedUser;
		}

		public void setSelectedUser(ElogUser selectedUser) {
			this.selectedUser = selectedUser;
		}

		public Elog.Type getSelectedType() {
			return selectedType;
		}

		public void setSelectedType(Elog.Type selectedType) {
			this.selectedType = selectedType;
		}

		public Elog.Status getSelectedStatus() {
			return selectedStatus;
		}

		public void setSelectedStatus(Elog.Status selectedStatus) {
			this.selectedStatus = selectedStatus;
		}

		public int getSelectedAge() {
			return selectedAge;
		}

		public void setSelectedAge(int selectedAge) {
			this.selectedAge = selectedAge;
		}

		public int getThread() {
			return thread;
		}

		public void setThread(int thread) {
			this.thread = thread;
		}
	}

}
